﻿using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

namespace Trade.Journal.Controls
{
    public class OpportunitySelecter : Control
    {
        private WrapPanel PART_Panel;
        private bool IsBeginInit; 

        public BasicType? SelectedBasicType
        {
            get { return (BasicType?)GetValue(SelectedBasicTypeProperty); }
            set { SetValue(SelectedBasicTypeProperty, value); }
        }

        // Using a DependencyProperty as the backing store for SelectedSpecialType.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SelectedBasicTypeProperty =
            DependencyProperty.Register("SelectedBasicType", typeof(BasicType?), typeof(OpportunitySelecter), new PropertyMetadata(null, new PropertyChangedCallback(OnSelectBasic)));

        private static void OnSelectBasic(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is OpportunitySelecter o && e.NewValue is BasicType s)
            {
                o.CategoryTypes = o.CategoryTypeDict[s];
                o.InitSelectedCategoryType();

                //if (s != o.Opportunity?.BasicType)
                //    o.Opportunity = new Opportunity() { BasicType = s };
            }
        }


        private void InitSelectedCategoryType()
        {
            SelectedCategoryType.Clear();
            SelectedCategoryType.Add(null);
            return;

            if (SelectedCategoryType.Count == 0)
                SelectedCategoryType.Add(null);
            else if (SelectedCategoryType.Count >= 1)
                SelectedCategoryType[0] = null;
            for (int i = 1; i < SelectedCategoryType.Count; i++)
                SelectedCategoryType.RemoveAt(i);
        }

        public ObservableCollection<CategoryType?> SelectedCategoryType { get; } = new ObservableCollection<CategoryType?>();
        //public ObservableCollection<CategoryType?> SelectedCategoryType
        //{
        //    get { return (ObservableCollection<CategoryType?>)GetValue(SelectedCategoryTypeProperty); }
        //    set { SetValue(SelectedCategoryTypeProperty, value); }
        //}

        //// Using a DependencyProperty as the backing store for SelectedCategoryType.  This enables animation, styling, binding, etc...
        //public static readonly DependencyProperty SelectedCategoryTypeProperty =
        //    DependencyProperty.Register("SelectedCategoryType", typeof(ObservableCollection<CategoryType?>), typeof(OpportunitySelecter),
        //        new PropertyMetadata(new ObservableCollection<CategoryType?>(new CategoryType?[1]), new PropertyChangedCallback(OnSelectedCategoryType)));

        //private static void OnSelectedCategoryType(DependencyObject d, DependencyPropertyChangedEventArgs e)
        //{
        //    if (d is OpportunitySelecter o && e.NewValue is IEnumerable<CategoryType> s && o.SelectedBasicType.HasValue)
        //    {
        //        o.Opportunity = new Opportunity() { BasicType = o.SelectedBasicType.Value, CategoryType = s.ToArray() };
        //    }
        //}

        public CategoryType[] CategoryTypes
        {
            get { return (CategoryType[])GetValue(CategoryTypesProperty); }
            set { SetValue(CategoryTypesProperty, value); }
        }

        // Using a DependencyProperty as the backing store for CategoryTypes.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CategoryTypesProperty =
            DependencyProperty.Register("CategoryTypes", typeof(CategoryType[]), typeof(OpportunitySelecter), new PropertyMetadata(null));




        public Opportunity Opportunity
        {
            get { return (Opportunity)GetValue(OpportunityProperty); }
            set { SetValue(OpportunityProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Opportunity.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty OpportunityProperty =
            DependencyProperty.Register("Opportunity", typeof(Opportunity), typeof(OpportunitySelecter), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(OnSetOpportunity)));

        private static void OnSetOpportunity(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is OpportunitySelecter s && e.NewValue is Opportunity o)
            {
                if (!o.IsWellFormed )
                    return;

                s.IsBeginInit = true;
                //if (s.SelectedBasicType != o.BasicType)
                s.SelectedBasicType = o.BasicType;

                //s.SelectedCategoryType.CollectionChanged -= s.SelectedCategoryType_CollectionChanged;
                s.SelectedCategoryType.Clear();
                foreach (var item in o.CategoryType)
                {
                    s.SelectedCategoryType.Add(item);
                }
                //s.SelectedCategoryType.CollectionChanged += s.SelectedCategoryType_CollectionChanged;
                s.IsBeginInit = false;
            }
        }

        public BasicType[] SpecialTypes { get; } = new BasicType[] { Trade.Journal.BasicType.Normal, Trade.Journal.BasicType.Overweight, Trade.Journal.BasicType.Resonate, BasicType.Balance };

        private Dictionary<BasicType, CategoryType[]> CategoryTypeDict { get; } = new Dictionary<BasicType, CategoryType[]>
            {
                { BasicType.Normal, new CategoryType[] { CategoryType.Rectangle, CategoryType.FlagShaped,CategoryType.Channel, CategoryType.Triangle, CategoryType.DoublePole, CategoryType.HeadShoulder } },
                { BasicType.Overweight, new CategoryType[] { CategoryType.Rectangle, CategoryType.FlagShaped, CategoryType.Triangle, CategoryType.VShaped, CategoryType.Heteroideus } },
                { BasicType.Resonate, new CategoryType[] { CategoryType.Rectangle, CategoryType.FlagShaped, CategoryType.Triangle, CategoryType.DoublePole, CategoryType.HeadShoulder, CategoryType.VShaped, CategoryType.Heteroideus } },
                { BasicType.Balance, new CategoryType[]{ CategoryType.Pole, CategoryType.Boundary} }
        };





        public OpportunitySelecter()
        {
            SelectedCategoryType.CollectionChanged += SelectedCategoryType_CollectionChanged;
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            PART_Panel = Template.FindName("PART_Panel", this) as WrapPanel;
        }

        private void SelectedCategoryType_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            if (SelectedBasicType == BasicType.Resonate /*&& SelectedCategoryType.LastOrDefault() != null*/)
            {
                //SelectedCategoryType.Add(null);
                //if (PART_Panel != null && PART_Panel.Children.Count <= SelectedCategoryType.Count)
                //{
                //    var cmb = new ComboBox { ItemsSource = CategoryTypes, ItemTemplate = TryFindResource("DataTemplate.EnumDescription") as DataTemplate };
                //    cmb.SetBinding(ComboBox.SelectedItemProperty, new Binding($"SelectedCategoryType[{SelectedCategoryType.Count - 1}]") { Source = this });
                //    PART_Panel.Children.Add(cmb);
                //}
            }

            if (SelectedCategoryType.LastOrDefault() != null) SelectedCategoryType.Add(null);

            if (!IsBeginInit)
            {
                UpdateOpportunity();
            }
        }

        private void UpdateOpportunity()
        {
            if (!SelectedBasicType.HasValue || SelectedCategoryType.Count == 0)
                return;

            if (Opportunity == null|| Opportunity.BasicType != SelectedBasicType.Value || !IsSame(Opportunity.CategoryType, SelectedCategoryType))
                Opportunity = new Opportunity { BasicType = SelectedBasicType.Value, CategoryType = SelectedCategoryType.Where(x => x.HasValue).Select(x => x.Value).ToArray() };
        }

        private bool IsSame(CategoryType[] a, ObservableCollection<CategoryType?> b)
        {
            if (a.Length != b.Count)
                return false;

            for (int i = 0; i < a.Length; i++)
            {
                if (a[i] != b[i])
                    return false;
            }
            return true;
        }
    }
}
